#include "kamera.h"
#include <stdio.h>
#include <math.h>

int mausX=0, mausY=0;

int spinZ = 0, spinY =0, spinX = 0; //Parameter zum drehen der Kamera
//Parameter fuer due gluLookAt-Funktion
float kameraLookAtX = 78.0, kameraLookAtY = 4.0, kameraLookAtZ = 32.0;
float kameraStandpunktX = 81.0, kameraStandpunktY = 4.0, kameraStandpunktZ = 32.0;
//wenn die Kamera bewegt wird, muessen auch die lookAt-Parameter mit der Kamera mitgehen
float lookAtVerschiebungX = 81.0, lookAtVerschiebungZ = 32.0;
//Richtungsvektor, in die die Kamera sich bewegt, wenn W oder S gedrueckt werden
float vektorBewegungWS[2] = {-1.0, 0.0};
//Richtungsvektor, in die die Kamera sich bewegt, wenn A oder D gedrueckt werden
float vektorBewegungAD[2] = {0.0, -1.0};

//status zeigt an, ob sich die Kreisfunktion oberhalb oder unterhalb der x-Achse befindet
int status = 0;
//Groesse der Veraenderung des Parameters x der Kreisfunktion f(x) = sqrt(9 - x^2) -> Radius 3
float speedOfCamMouse = 0.03;

/*
 * Die Kreisfunktion lautet:  kameraLookAtZ(kameraLookAtX) = sqrt(9 - kameraLookAtX^2)
 *
 * Man schaut also immer auf den Punkt 3 Einheiten von der Kamera weg geradeaus.
 * Die Kamera befindet sich immer im Ursprung (kameraStandpunktX und kameraStandpunktZ)
 * Der eingezeichnete Vektor ist der Vektor, den man quasi mit der Maus steuert,
 * also das kameraLookAtX und kameraLookAtZ.
 * Wenn man die Kamera mit der Maus dreht, dann veraendert man die X-Koordinate und
 * eine neue Z-Koordinate wird dazu errechnet.
 *
 * Die Vektoren vektorBewegungWS und -AD nehmen die Drehung auf
 * und geben das an die Tastatur-Steuerung weiter, damit man sich auch wieder in die 
 * Richtung bewegt, in die man schaut. DIe Vektoren werden zusaetzlich normiert, damit
 * man sich immer um eine Einheit sich bewegt.
 *
 *
 *                   Y |
 *                     |
 *                    (9|0) 
 *               , - ~ ~ ~ - ,
 *           , ' <-\-> |       ' ,            status=0
 *         ,        \  |           ,
 *        ,          \ |            ,
 *       ,            \|             ,
 *  -----,---------------------------,---------> X
 * (0|-9),          (0|0)            , (0|9)
 *        ,            |            ,
 *         ,           |           ,
 *           ,         |        , '           status=1
 *             ' - , _ | _ ,  '
 *                  (-9|0)
 *                     |
 *                     |
 */
void mausKamera(int x, int y) {
	//Drehung rechts...
	if(x>mausX) {
		float erg = (kameraLookAtX-lookAtVerschiebungX)* (kameraLookAtX-lookAtVerschiebungX);
		if(status == 0) {
			if(kameraLookAtX < (3.0+lookAtVerschiebungX)) {
				//Ueberpruefung, ob Wert unter der Wurzel groesser 0 ist...
				if(erg < 9.0) {
					kameraLookAtZ = -sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX += speedOfCamMouse;
				}
				//...sonst muss dieser geaendert werden.
				else {
					printf("!!! NaN !!!\n");
					erg -= 0.0001;
					kameraLookAtZ = -sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX += speedOfCamMouse;
				}
			}
			else {
				status = 1;
				kameraLookAtX = 3.0+lookAtVerschiebungX;
				kameraLookAtZ = 0.0+lookAtVerschiebungZ;
			}
		}
		else {
			if(kameraLookAtX > -3.0+lookAtVerschiebungX) {
				if(erg < 9.0) {
					kameraLookAtZ = sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX -= speedOfCamMouse;
				}
				else {
					printf("!!! NaN !!!\n");
					erg -= 0.0001;
					kameraLookAtZ = -sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX -= speedOfCamMouse;
				}
			}
			else {
				status = 0;
				kameraLookAtX = -3.0+lookAtVerschiebungX;
				kameraLookAtZ = 0.0+lookAtVerschiebungZ;
			}
		}
	}
	//...und links.
	else if(x<mausX) {
		float erg = (kameraLookAtX-lookAtVerschiebungX)* (kameraLookAtX-lookAtVerschiebungX);
		if(status == 0) {
			if(kameraLookAtX >= -3.0+lookAtVerschiebungX) {
				if(erg < 9.0) {
					kameraLookAtZ = -sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX -= speedOfCamMouse;
				}
				else {
					printf("!!! NaN !!!\n");
					erg -= 0.0001;
					kameraLookAtZ = -sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX -= speedOfCamMouse;
				}
			}
			else {
				status = 1;
				kameraLookAtX = -3.0+lookAtVerschiebungX;
				kameraLookAtZ = 0.0+lookAtVerschiebungZ;
			}
		}
		else {
			if(kameraLookAtX <= 3.0+lookAtVerschiebungX) {
				if(erg < 9.0) {
					kameraLookAtZ = +sqrt( 9.0- erg)+lookAtVerschiebungZ;
					kameraLookAtX += speedOfCamMouse;
				}
				else {
					printf("!!! NaN !!!\n");
					erg -= 0.0001;
					kameraLookAtZ = +sqrt(9.0 - erg)+lookAtVerschiebungZ;
					kameraLookAtX += speedOfCamMouse;
				}
			}
			else {
				status = 0;
				kameraLookAtX = 3.0+lookAtVerschiebungX;
				kameraLookAtZ = 0.0+lookAtVerschiebungZ;
			}
		}
	}

	//hoch und runter
	if(y>mausY) {
		if(kameraLookAtY > -20.0) kameraLookAtY -= 0.1;
	}
	else if(y<mausY) {
		if(kameraLookAtY < 20.0) kameraLookAtY += 0.1;
	}
	mausX = x;
	mausY = y;

	//Bilde den Bewegungsvektor und normiere diesen
	vektorBewegungWS[0] = kameraLookAtX-lookAtVerschiebungX;
	vektorBewegungWS[1] = kameraLookAtZ-lookAtVerschiebungZ;
	mathfunctions::normiereVektor2D(vektorBewegungWS);
	vektorBewegungAD[0] = vektorBewegungWS[1] * -1;
	vektorBewegungAD[1] = vektorBewegungWS[0];

	glutPostRedisplay();
}

/*
 * Hier koennen die Grenzen eingestellt werden, in der man die Kamera
 * bewegen darf. Dabei sind die X- von den Z-Koordinaten getrennt.
 */
int kollisionsAbfrageX() {
	int sum = 0;
	//Status nicht auf dem Steg...
	if(aufSteg == 0) {
		if(kameraStandpunktX >= 7.0) {
			sum +=1;
		}
		if(kameraStandpunktX <= 146.0) {
			sum += 1;
		}
		if(sum == 2) return 1;
		else return 0;
	}
	//Status auf dem Steg...
	else {
		if(kameraStandpunktX >= 71.0) {
			sum +=1;
		}
		if(kameraStandpunktX <= 77.0) {
			sum += 1;
		}
		if(sum == 2) return 1;
		else return 0;
	}
}

float zMax = 148.0;
int aufStegY = 0;
int aufSteg = 0;
int kollisionsAbfrageZ() {
	int sum = 0;
	if(aufSteg == 0) {
		if(kameraStandpunktZ >= 9.0) {
			sum += 1;
		}
		if(kameraStandpunktZ <= zMax) {
			sum += 1;
		}
		if(sum == 2) return 1;
		else return 0;
	}
	else {
		if(kameraStandpunktZ >= zMax) {
			sum += 1;
		}
		if(kameraStandpunktZ <= 243.0) {
			sum += 1;
		}
		if(sum == 2) return 1;
		else return 0;
	}
}

void ueberpruefungAufSteg() {
	if(kameraStandpunktX >= 71.0 && kameraStandpunktX <= 77.0 && kameraStandpunktZ >= zMax && aufSteg == 0) {
		aufSteg = 1;
	}
	else if (kameraStandpunktZ < zMax && aufSteg == 1) {
		aufSteg = 0;
	}
	if(kameraStandpunktX >= 71.0 && kameraStandpunktX <= 77.0 && kameraStandpunktZ >= (zMax+5.0) && aufStegY == 0) {
		aufStegY = 1;
		kameraStandpunktY -= 4.0;
		kameraLookAtY -= 4.0;
	}
	else if (kameraStandpunktZ < (zMax+5.0) && aufStegY == 1) {
		aufStegY = 0;
		kameraStandpunktY += 4.0;
		kameraLookAtY += 4.0;
	}
}
